package com.hkemmm.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.hkemmm.bean.AuthUser;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JWTUtil {
    // 过期时间5分钟
    private static final long EXPIRE_TIME = 60L;

    //设置私钥
    private static final String SECRET = "hkemmmm";

    /**
     * 校验token是否正确
     *
     * @param token 密钥
     * @return 是否正确
     */
    public static boolean verify(String token, String username) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(token);
            return true;
        } catch (Exception exception) {
            return false;
        }
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     *
     * @return token中包含的用户名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("loginName").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     *
     * @return token中包含的用户名
     */
    public static String getPassword(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("password").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     *
     * @return token中包含的用户名
     */
    public static String getFieldValue(String token, String field) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(field).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 通过Token解析出roles
     *
     * @param token
     * @return
     */
    public static String getRolesByToken(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("roles").asString();
        } catch (JWTDecodeException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 通过Token解析出roles
     *
     * @param token
     * @return
     */
    public static AuthUser getAuthUser(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            AuthUser authUser = new AuthUser();
            Field[] fields = authUser.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                try {
                    String name = field.getName();
                    Object value = jwt.getClaim(transform(name.toString())).asString();
                    if (value != null && !name.equals("serialVersionUID")) {
                        if (field.getType().toString().equals("class java.lang.Integer")) {
                            field.set(authUser, Integer.valueOf(value.toString()));
                        } else {
                            if (!field.getType().toString().equals("interface java.util.List")) {
                                field.set(authUser, value);
                            }
                        }

                        if (field.getType().equals("class java.lang.String")) {
                            field.set(authUser, String.valueOf(value));
                        }
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return authUser;
        } catch (JWTDecodeException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 生成签名,5min后过期
     *
     * @param authUser
     * @return 加密的token
     */
    public static String sign(AuthUser authUser) {
        try {
            //jwt的header部分
            Map<String, Object> map = new HashMap<>();
            map.put("alg", "HS256");
            map.put("typ", "JWT");
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            Field[] fields = authUser.getClass().getDeclaredFields();
            String token = "";
            // 附带username信息
            JWTCreator.Builder builder = JWT.create().withHeader(map);
            for (Field field : fields) {
                field.setAccessible(true);
                try {
                    Object value = field.get(authUser);
                    String name = field.getName();
                    if (value != null && !name.equals("serialVersionUID")) {
                        builder.withClaim(transform(name.toString()), value.toString());
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            token = builder.sign(algorithm);
            return token;
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    //根据属性名生成表字段名
    private static String transform(String s) {
        if (!s.matches(".*?[A-Z].*?"))
            return s;
        StringBuilder sb = new StringBuilder();
        char[] c = s.toCharArray();
        int start = 0;
        int end = 0;
        for (int i = 0; i < c.length; i++) {
            if ('A' <= c[i] && c[i] <= 'Z' && i != 0) {
                start = end;
                end = i;
                sb.append(s.substring(start, end) + "_");
            }
        }
        sb.append(s.substring(end, c.length));
        return sb.toString().toLowerCase();
    }

    /**
     * 生成签名,5min后过期
     *
     * @param userName 用户名
     * @param userId   用户名
     * @return 加密的token
     */
    public static String sign(String userName, String userId) {
        try {
            //jwt的header部分
            Map<String, Object> map = new HashMap<>();
            map.put("alg", "HS256");
            map.put("typ", "JWT");
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            // 附带username信息
            return JWT.create()
                    .withHeader(map)
                    .withClaim("username", userName)
                    .withClaim("userId", userId)
//                    .withClaim("roles","SELECT,DROP,DELETE")
                    .withExpiresAt(date)
                    .sign(algorithm);
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    /**
     * 校验token是否有效
     *
     * @param token
     * @return
     */
    public static boolean verifyToken(String token) {
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET))
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            Map<String, Claim> claims = jwt.getClaims();
            return true;
        } catch (Exception e) {
            return false;
        }

    }
}
